﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ResponseTest
{
    public partial class Form1 : Form
    {
        bool _start;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            comboBoxProtocol.SelectedIndex = 0;

            checkBoxNeedRecv_CheckedChanged(null, null);
        }

        private void checkBoxNeedRecv_CheckedChanged(object sender, EventArgs e)
        {
            textBoxRecvIP.Enabled = checkBoxNeedRecv.Checked;
            textBoxRecvPort.Enabled = checkBoxNeedRecv.Checked;
        }

        private async void buttonStart_Click(object sender, EventArgs e)
        {
            buttonStart.Enabled = false;
            buttonStop.Enabled = true;

            if (comboBoxProtocol.SelectedIndex == 0)
            {
                _start = true;

                if (checkBoxNeedRecv.Checked)
                    await Task.Run(_startTcp2);
                else
                    await Task.Run(_startTcp);
            }
            else
            {
                if (checkBoxNeedRecv.Checked)
                {
                    var ret = MessageBox.Show(this, "Udp 协议不支持另开接收端。是否继续？", "提示", MessageBoxButtons.YesNoCancel);
                    if (ret != DialogResult.Yes)
                        return;
                }

                _start = true;

                await Task.Run(_startUdp);
            }

            buttonStart.Enabled = true;
            buttonStop.Enabled = false;

            buttonStart.Text = "开始";
        }

        private void _startTcp()
        {
            int port = 0;
            if (!int.TryParse(textBoxPort.Text.Trim(), out port))
            {
                textBoxPort.Focus();
                return;
            }

            IPAddress addr;
            if (!IPAddress.TryParse(textBoxIP.Text.Trim(), out addr))
            {
                textBoxIP.Focus();
                return;
            }

            int trys = 0;
            if (!int.TryParse(textBoxTrys.Text.Trim(), out trys))
            {
                textBoxTrys.Focus();
                return;
            }

            int interval = 0;
            if (!int.TryParse(textBoxInterval.Text.Trim(), out interval))
            {
                textBoxInterval.Focus();
                return;
            }

            var client = new TcpClient();
            var task = client.ConnectAsync(addr, port);
            task.Wait(2000);
            if (!client.Connected)
            {
                MessageBox.Show(this, "连接失败");
                return;
            }

            var sendBytes = Encoding.Default.GetBytes(textBoxSend.Text.Trim());

            var stream = client.GetStream();
            var buf = new byte[4096];
            int count = 0;
            long msecs = 0;
            int success = 0;

            var watch = Stopwatch.StartNew();
            long begin = 0;

            while (_start)
            {
                ++count;
                this.Invoke((Action)(() => buttonStart.Text = (trys - count).ToString()));

                stream.Write(sendBytes, 0, sendBytes.Length);

                begin = watch.ElapsedMilliseconds;

                var rtask = stream.ReadAsync(buf, 0, 4096);
                if (!rtask.Wait(2000))
                    continue;

                if (rtask.Result == 0)
                {
                    this.Invoke((Action)(() => textBoxResult.AppendText("连接中断\r\n")));
                    break;
                }

                msecs += watch.ElapsedMilliseconds - begin;

                if (rtask.Result == sendBytes.Length)
                    ++success;

                if (count == trys)
                    break;

                Thread.Sleep(interval);
            }

            client.Close();

            var result = string.Format("服务器 {0} Tcp 端口 {1}，数据长度 {2}，发送间隔 {3}，共尝试 {4} 次，成功 {5} 次。接收耗时 {6} 毫秒，平均耗时 {7} 毫秒\r\n", addr, port, sendBytes.Length, interval, count, success, msecs, (int)((double)msecs / count));
            this.Invoke((Action)(() => textBoxResult.AppendText(result)));
        }

        private void _startUdp()
        {
            int port = 0;
            if (!int.TryParse(textBoxPort.Text.Trim(), out port))
            {
                textBoxPort.Focus();
                return;
            }

            IPAddress addr;
            if (!IPAddress.TryParse(textBoxIP.Text.Trim(), out addr))
            {
                textBoxIP.Focus();
                return;
            }

            int trys = 0;
            if (!int.TryParse(textBoxTrys.Text.Trim(), out trys))
            {
                textBoxTrys.Focus();
                return;
            }

            int interval = 0;
            if (!int.TryParse(textBoxInterval.Text.Trim(), out interval))
            {
                textBoxInterval.Focus();
                return;
            }

            var client = new UdpClient(0);
            client.Connect(addr, port);

            var sendBytes = Encoding.Default.GetBytes(textBoxSend.Text.Trim());

            var buf = new byte[4096];
            int count = 0;
            long msecs = 0;
            int success = 0;

            var watch = Stopwatch.StartNew();
            long begin = 0;

            while (_start)
            {
                ++count;
                this.Invoke((Action)(() => buttonStart.Text = (trys - count).ToString()));

                client.Send(sendBytes, sendBytes.Length);

                begin = watch.ElapsedMilliseconds;

                var task = client.ReceiveAsync();
                if (!task.Wait(2000))
                    continue;

                msecs += watch.ElapsedMilliseconds - begin;

                if (task.Result.Buffer.Length == sendBytes.Length)
                    ++success;

                if (count == trys)
                    break;

                Thread.Sleep(interval);
            }

            client.Close();

            var result = string.Format("服务器 {0} Udp 端口 {1}，数据长度 {2}，发送间隔 {3}，共尝试 {4} 次，成功 {5} 次。接收耗时 {6} 毫秒，平均耗时 {7} 毫秒\r\n", addr, port, sendBytes.Length, interval, count, success, msecs, (int)((double)msecs / count));
            this.Invoke((Action)(() => textBoxResult.AppendText(result)));
        }

        private void _startTcp2()
        {
            int port = 0;
            if (!int.TryParse(textBoxPort.Text.Trim(), out port))
            {
                textBoxPort.Focus();
                return;
            }

            IPAddress addr;
            if (!IPAddress.TryParse(textBoxIP.Text.Trim(), out addr))
            {
                textBoxIP.Focus();
                return;
            }

            int port2 = 0;
            if (!int.TryParse(textBoxPort.Text.Trim(), out port2))
            {
                textBoxRecvPort.Focus();
                return;
            }

            IPAddress addr2;
            if (!IPAddress.TryParse(textBoxIP.Text.Trim(), out addr2))
            {
                textBoxRecvIP.Focus();
                return;
            }

            int trys = 0;
            if (!int.TryParse(textBoxTrys.Text.Trim(), out trys))
            {
                textBoxTrys.Focus();
                return;
            }

            int interval = 0;
            if (!int.TryParse(textBoxInterval.Text.Trim(), out interval))
            {
                textBoxInterval.Focus();
                return;
            }

            var client = new TcpClient();
            var task = client.ConnectAsync(addr, port);
            task.Wait(2000);
            if (!client.Connected)
            {
                MessageBox.Show(this, "连接失败");
                return;
            }

            var client2 = new TcpClient();
            task = client2.ConnectAsync(addr2, port2);
            task.Wait(2000);
            if (!client2.Connected)
            {
                MessageBox.Show(this, "接收侧连接失败");
                return;
            }

            var sendBytes = Encoding.Default.GetBytes(textBoxSend.Text.Trim());

            var stream = client.GetStream();
            var stream2 = client2.GetStream();
            var buf = new byte[4096];
            int count = 0;
            long msecs = 0;
            int success = 0;

            var watch = Stopwatch.StartNew();
            long begin = 0;

            while (_start)
            {
                ++count;
                buttonStart.Text = (trys - count).ToString();

                stream.Write(sendBytes, 0, sendBytes.Length);

                begin = watch.ElapsedMilliseconds;

                var taskr = stream2.ReadAsync(buf, 0, 4096);
                if (!taskr.Wait(2000))
                    continue;

                if (taskr.Result == 0)
                {
                    textBoxResult.AppendText("连接中断");
                    textBoxResult.AppendText("\n");
                    break;
                }

                msecs += watch.ElapsedMilliseconds - begin;

                buttonStart.Text = (trys - count).ToString();

                if (taskr.Result == sendBytes.Length)
                    ++success;

                if (count == trys)
                    break;

                Thread.Sleep(interval);
            }

            client.Close();

            var result = string.Format("服务器 {0} Tcp 端口 {1}，数据长度 {2}，发送间隔 {3}，共尝试 {4} 次，成功 {5} 次。接收耗时 {6} 毫秒，平均耗时 {7} 毫秒\r\n", addr, port, sendBytes.Length, interval, count, success, msecs, (int)((double)msecs / count));
            textBoxResult.AppendText(result);
            textBoxResult.AppendText("\r\n");
        }

        private void buttonStop_Click(object sender, EventArgs e)
        {
            _start = false;
        }

        private void buttonClear_Click(object sender, EventArgs e)
        {
            textBoxResult.Clear();
        }
    }
}
